// UInt & SInt
val myUInt = UInt(8 bits) // 直接声明固定宽度的 UInt
myUInt := U(2,8 bits) // 声明固定宽度的 UInt 并初始化
myUInt := U(2) // 声明宽度不固定的 UInt 并初始化
myUInt := U"0000_0101"  // 字符串方式中，默认为二进制数
myUInt := U"h1A"        // 基数可以是      x (base 16)
                        //               h (base 16)
                        //               d (base 10)
                        //               o (base 8)
                        //               b (base 2)
myUInt := U"8'h1A"
myUInt := 2             // 使用 Scala 的 Int 数据类型直接赋值（默认为 UInt）

val myBool := myUInt === U(7 -> true,(6 downto 0) -> false)
val myBool := myUInt === U(myUInt.range -> true)

// 在不明确声明 UInt 还是 SInt 时，可以使用 [default -> ???] 进行声明
myUInt := (default -> true)                        // Assign myUInt with "11111111"
myUInt := (myUInt.range -> true)                   // Assign myUInt with "11111111"
myUInt := (7 -> true, default -> false)            // Assign myUInt with "10000000"
myUInt := ((4 downto 1) -> true, default -> false) // Assign myUInt with "00011110"

// 位运算
val a, b, c = SInt(32 bits)
c := ~(a & b) // a 与 b 后取反

val all_1 = a.andR // 等价于 Verilog 中的 &a，表示自身所有位进行与运算，得到 1 位的结果

// 移位（SInt 默认为算术移位，即右移时保持符号位不变）
val uint_10bits = uint_8bits << 2  // 左移 (得到 10 位的结果)
val shift_8bits = uint_8bits |<< 2 // 左移 (得到 8 位的结果)

// 循环移位
val myBits = uint_8bits.rotateLeft(3) // 左循环移位

// 置位和清零
val a = B"8'x42"
when(cond) {
  a.setAll() // 当 cond 为真时，将 a 置位（所有位为 1）
}otherwise{
  a.clearAll() // 当 cond 为假时，将 a 清零（所有位为 0）
}

val Sres = mySInt_1 + mySInt_2 // res 为 SInt
val Ures = myUInt_1 - myUInt_2 // res 为 UInt

// 注意，比较时左右数据类型必须一致
myBool := mySInt_1 > mySInt_2

myBool := myUInt_8bits >= U(3, 8 bits)

when(myUInt_8bits === 3) {
  // 注意这里的相等符号，是 ===
}

when(mySInt_16bits =/= -12){
  // 这里的不等号，是 =/=
}

// SInt 转 Bits
val myBits = mySInt.asBits

// UInt 转 Bool 向量
val myVec = myUInt.asBools

// Bits 转 SInt
val mySInt = S(myBits)

// SInt 转 UInt
val myUInt = mySInt.asUInt

// UInt 转 SInt
val mySInt_2 = myUInt.asSInt

// 取第 4 位
val myBool = myUInt(4)

// 将 mySInt 的第 1 位置位
mySInt(1) := True

// 范围
val myUInt_8bits = myUInt_16bits(7 downto 0) // 取 [0,7] 位
val myUInt_7bits = myUInt_16bits(0 to 6) // 取 [0,6]
val myUInt_6bits = myUInt_16Bits(0 until 6) // 取 [0,6)

mySInt_8bits(3 downto 0) := mySInt_4bits

myBool := mySInt.lsb  // 取 LSB，等价于取 mySInt(0)

// 位拼接
val mySInt = mySInt_1 @@ mySInt_1 @@ myBool
val myBits = mySInt_1 ## mySInt_1 ## myBool

// 位分割
val sel = UInt(2 bits)
val mySIntWord = mySInt_128bits.subdivideIn(32 bits)(sel)
    // sel = 0 => mySIntWord = mySInt_128bits(127 downto 96)
    // sel = 1 => mySIntWord = mySInt_128bits( 95 downto 64)
    // sel = 2 => mySIntWord = mySInt_128bits( 63 downto 32)
    // sel = 3 => mySIntWord = mySInt_128bits( 31 downto  0)

// 位反转（顺序颠倒，如 11110000 变为 00001111）
val myVector   = mySInt_128bits.subdivideIn(32 bits).reverse
val mySIntWord = myVector(sel)

// 重置大小
myUInt_32bits := U"32'x112233344"
myUInt_8bits  := myUInt_32bits.resized       // 自动判定新宽度 (myUInt_8bits = 0x44)
myUInt_8bits  := myUInt_32bits.resize(8)     // 手动确定新宽度 (myUInt_8bits = 0x44)

// 取绝对值
mySInt_abs := mySInt.abs



// Bool
val myBool_1 = Bool()          // 声明 Bool 类型变量
myBool_1 := False            // 使用 := 符号赋值

val myBool_2 = False         // 直接声明并初始化一个 Bool 类型变量

val myBool_3 = Bool(5 > 12)  // 使用 Scala 的 Boolean 类型声明 Bool 类型变量

val a, b, c = Bool()
val res = (!a & b) ^ c   // 逻辑运算

val d = False
when(cond) {
  d.set()    // 置位，等价于 d := True
}

val e = False
e.setWhen(cond) // 等价于 when(cond) { d := True }

val f = RegInit(False) fallWhen(ack) setWhen(req)
 /** 等价于以下代码
  * when(f && ack) { f := False } 当 ack 信号为真时，f 为假
  * when(req) { f := True } 当 req 信号为真时，f 为真
  * or
  * f := req || (f && !ack)
  */

// 注意赋值顺序
val g = RegInit(False) setWhen(req) fallWhen(ack)
// 等价于 g := ((!g) && req) || (g && !ack)

when(myBool_1.rise(False)) {
    // 当检测到 myBool_1 出现上升沿时
}


val edgeBundle = myBool_2.edges(False) // 这里是一个 Bundle 数据类型，记录了 myBool_2 的边沿信息（rise, fall, toggle）
when(edgeBundle.rise) {
    // 当检测到 myBool_2 出现上升沿时
}
when(edgeBundle.fall) {
    // 当检测到 myBool_2 出现下降沿时
}
when(edgeBundle.toggle) {
    // 当检测到 myBool_2 信号翻转时
}



// Bundle
case class myBundle extends Bundle {
  // 直接定义 Bundle
  val bundleItem0 = AnyType
  val bundleItem1 = AnyType
  val bundleItemN = AnyType
}

case class myBundle(dataWidth: Int) extends Bundle {
  // 带有条件的定义 Bundle
  val data = (dataWidth > 0) generate (UInt(dataWidth bits))
}

case class TestBundle () extends Component {
  val io = new Bundle {
    val we      = in     Bool()
    val addrWr  = in     UInt (7 bits)
    val dataIn  = slave  (CommonDataBus())

    val addrRd  = in     UInt (7 bits)
    val dataOut = master (CommonDataBus())
  }

  val mm = Ram3rdParty_1w_1rs (G_DATA_WIDTH = io.dataIn.getBitsWidth,
                               G_ADDR_WIDTH = io.addrWr.getBitsWidth,
                               G_VENDOR     = "Intel_Arria10_M20K")

  mm.io.clk_in    := clockDomain.readClockWire
  mm.io.clk_out   := clockDomain.readClockWire

  mm.io.we        := io.we
  mm.io.addr_wr   := io.addrWr.asBits
  mm.io.d         := io.dataIn.asBits

  mm.io.addr_rd   := io.addrRd.asBits
  io.dataOut.assignFromBits(mm.io.q)
}

val io = new Bundle {
  val input  = in (Color(8))
  val output = out(Color(8))
}

case class HandShake(payloadWidth: Int) extends Bundle with IMasterSlave {
  val valid   = Bool()
  val ready   = Bool()
  val payload = Bits(payloadWidth bits)

  // 若使用 master/slave 方式，则必须先实现 asMaster() 函数
  // 这一函数将定义各个信号的方向
  override def asMaster(): Unit = {
    out(valid, payload)
    in(ready)
  }
}

val io = new Bundle {
  val input  = slave(HandShake(8))
  val output = master(HandShake(8))
}



// 变量赋值
val a, b, c = UInt(4 bits)
a := 0
b := a
a := 1  // a := 1 最终赋值成功，且在本时钟周期内，b 和 c 的值也都是 1
c := a

var x = UInt(4 bits) // 注意这里的 x 是 var 类型
val y, z = UInt(4 bits)
x := 0
y := x      // y 读到的 x 是 0
x \= x + 1
z := x      // z 读到的 x 是 1

// 自动连接两个 UART 接口
uartCtrl.io.uart <> io.uart

// \= 源码
def \(that: T): T = {

    val globalData = GlobalData.get

    val ctx = DslScopeStack.set(_data.parentScope)

    val swapContext = _data.parentScope.swap()
    val ret = cloneOf(that) // 先进行了电路对象的复制

    ret := _data // 将当前电路对象赋值给了新的电路对象

    swapContext.appendBack()
    ctx.restore()

    ret.allowOverride
    ret := that // 将 \= 右边的电路对象再赋值给新的电路对象

    (this, ret) match {
      case (from: Data with Nameable, to: Data with Nameable) => {
        val t = from.getTag(classOf[VarAssignementTag]) match {
          case Some(t) => t
          case None => new VarAssignementTag(from)
        }
        t.id += 1
        to.setCompositeName(t.from,t.id.toString)

        from.removeTag(t)
        ret.addTag(t)
      }
      case _ =>
    }

    ret
}
